﻿using System.ComponentModel;
using System.Security.Claims;
using ApiLib.Common;
using ApiLib.Controllers;
using ApiLib.Utils;
using Furion;
using Microsoft.AspNetCore.Http;

namespace ApiLib.Models;

/// <summary>
/// 认证
/// </summary>
public abstract class AbstractBaseAuthorization : IBaseAuthorization
{
    /// <summary>
    /// 初始化权限，不需要权限的程序，可以设置为false
    /// </summary>
    public virtual bool InitPermission { get; set; } = true;

    /// <summary>
    /// 权限类
    /// </summary>
    public virtual Type? SsType { get; set; }

    /// <summary>
    /// 保存的权限，默认：RoleSave
    /// </summary>
    public virtual string SsSave { get; set; } = "RoleSave";

    /// <summary>
    /// 保存角色用户，默认：RoleSaveUsers
    /// </summary>
    public virtual string SsSaveUsers { get; set; } = "RoleSaveUsers";

    /// <summary>
    /// 全部权限
    /// </summary>
    protected readonly HashSet<string> AllPermissions = new();

    /// <summary>
    /// 全部权限
    /// </summary>
    protected readonly List<RolePermission> RolePermissions = new();

    private static bool _permissionInited = false;
    private static readonly object _permissionLock = new object();

    /// <summary>
    /// 初始化权限
    /// </summary>
    /// <exception cref="MyActionException"></exception>
    protected virtual void InitRolePermission()
    {
        if (_permissionInited)
        {
            return;
        }

        lock (_permissionLock)
        {
            if (_permissionInited)
            {
                return;
            }

            if (SsType == null)
            {
                throw CommonUtil.ActionException("未定义权限类，需要定义权限类对象。");
            }

            var types = SsType.Assembly.GetTypes().Where(t => t.DeclaringType == SsType);
            foreach (var type in types)
            {
                var typeDesc =
                    Attribute.GetCustomAttribute(type, typeof(DescriptionAttribute)) as DescriptionAttribute;
                var fieldInfos = type.GetFields();
                foreach (var field in fieldInfos)
                {
                    var perm = field.GetValue(null)?.ToString();
                    if (!string.IsNullOrEmpty(perm))
                    {
                        AllPermissions.Add(perm);
                    }

                    var attribute =
                        Attribute.GetCustomAttribute(field, typeof(DescriptionAttribute)) as DescriptionAttribute;
                    RolePermissions.Add(new RolePermission()
                    {
                        Name = attribute?.Description ?? "未定义",
                        Permission = perm ?? "未定义",
                        Group = type.Name,
                        GroupName = typeDesc?.Description ?? "未定义分类"
                    });
                }
            }
            _permissionInited = true;
        }
    }

    /// <summary>
    /// 获取全部权限
    /// </summary>
    /// <returns></returns>
    public virtual HashSet<string> GetAllPermissions()
    {
        InitRolePermission();
        return AllPermissions;
    }

    /// <summary>
    /// 权限字符串列表
    /// </summary>
    /// <returns></returns>
    public virtual List<RolePermission> GetRolePermissions()
    {
        InitRolePermission();
        return RolePermissions;
    }
    
    /// <summary>
    /// 获取token
    /// </summary>
    /// <param name="request"></param>
    /// <returns></returns>
    /// <exception cref="NotImplementedException"></exception>
    public virtual string GetToken(HttpRequest? request = null)
    {
        var token = App.User?.FindFirstValue(ClaimTypes.Authentication) ?? "";
        if (string.IsNullOrEmpty(token))
        {
            token = request?.Headers.Authorization.ToString() ?? "";
        }
        return token;
    }
    
    /// <summary>
    /// 认证，根据token(会自动获取token)从缓存中返回用户。
    /// <code>
    /// var token = GetToken();
    /// if (string.IsNullOrEmpty(token))
    /// {
    ///     return default;
    /// }
    /// return DbHelper.GetUserCache&lt;T>("token_" + token);
    /// </code>
    /// </summary>
    /// <param name="request">http请求</param>
    /// <returns></returns>
    public abstract IBaseUser? Authorization(HttpRequest? request = null);

    /// <summary>
    /// 获取用户,从源地址(数据库)获取用户
    /// <code>
    /// if (sid == null)
    /// {
    ///     return default;
    /// }
    /// if (int.TryParse(sid, out var id) &amp;&amp; id > 0)
    /// {
    ///     return DbHelper.Db.Queryable&lt;T>()
    ///         .IgnoreColumns(info => info.Password)
    ///         .First(userinfo => userinfo.Id == id);
    /// }
    /// return default;
    /// </code>
    /// </summary>
    /// <param name="sid"></param>
    /// <returns></returns>
    public abstract IBaseUser? GetUser(string? sid);
}